package com.eltonkent.dashboard.service.requesthandler;

import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import com.eltonkent.dashboard.constants.ApplicationConstants;
import com.eltonkent.dashboard.data.container.Container;
import com.eltonkent.dashboard.data.container.GeoCodeContainer;
import com.eltonkent.dashboard.service.ServiceManagerImpl;
import com.eltonkent.dashboard.service.helper.HttpServiceHelper;
import com.eltonkent.dashboard.service.responsehandler.YahooReverseCodeHandler;
import com.eltonkent.dashboard.util.gps.WebResponseNotificationListener;

/**
 * This request can be used for both reverse coding as well as obtaining the
 * WOEID (where on earth id) for a given latitude and longitude.
 * <p>
 * The WOEID is used by many webservices. The weather information in particular
 * is obtained by the WOEID.
 * </p>
 * 
 * @author elton.stephen.kent
 * 
 */
public class YahooReverseCodeRequest extends HttpRequest {

	private final Double latitude;
	private final Double longitude;
	/* Check if this request is for weather */
	private final boolean isForWeather;

	/**
	 * Creates a new Yahoo reverse geocoding request
	 * 
	 * @param listener
	 *            Address callback
	 * @param latitude
	 *            latitude of the place
	 * @param longitude
	 *            longitude of the place
	 * @param forWeather
	 *            flag to indicate if this request is to be used for reverse
	 *            geocoding or for obtaining weather information
	 */
	public YahooReverseCodeRequest(WebResponseNotificationListener listener,
			Double latitude, Double longitude, boolean forWeather) {
		super(listener);
		this.latitude = latitude;
		this.longitude = longitude;
		this.isForWeather = forWeather;
	}

	@Override
	public Container call() throws Exception {
		HttpEntity httpEntity = httpServiceHelper.execute();
		InputStream is = httpEntity.getContent();
		YahooReverseCodeHandler xmlHandler = new YahooReverseCodeHandler();
		GeoCodeContainer container = xmlHandler.deserialize(is);
		return container;
	}

	@Override
	public void postExecute(Container container, Throwable throwable) {
		if (container != null) {
			GeoCodeContainer geoContainer = (GeoCodeContainer) container;
			geoContainer.setLatitude(latitude);
			geoContainer.setLongitude(longitude);
			if (isForWeather) {
				/* launch weather request */
				if (geoContainer.getWoeid() != null) {
					/*
					 * Yahoo could not obtain the WOEID for the given
					 * coordinates
					 */
					YahooWeatherRequest weather = new YahooWeatherRequest(
							listener, geoContainer.getWoeid());
					ServiceManagerImpl.getInstance().submit(weather);
				} else {
					/*
					 * launch google reverse code service, which then launches
					 * the weather service
					 */
					String lastKnownAddress = listener.getLastKnownAddress();
					/**
					 * If the last obtained reverse coding request is available, then directly launch the weather request.
					 */
					if (lastKnownAddress != null) {
						GoogleWeatherRequest googleWeather=new GoogleWeatherRequest(listener, lastKnownAddress);
						ServiceManagerImpl.getInstance().submit(googleWeather);
					} else {
						GoogleReverseCodeRequest reverseReq = new GoogleReverseCodeRequest(
								listener, latitude, longitude, true);
						ServiceManagerImpl.getInstance().submit(reverseReq);
					}
				}
			} else {
				/* notify address */
				listener.notifyAddress(geoContainer);
			}
		}
	}

	@Override
	public void preExecute() throws Exception {
		httpServiceHelper = new HttpServiceHelper(new URI(
				ApplicationConstants.URL_YAHOO_REVERSE_CODING));
		List<NameValuePair> requestParameter = new ArrayList<NameValuePair>();
		NameValuePair param = new BasicNameValuePair("q", latitude.toString()
				+ ",+" + longitude.toString());
		requestParameter.add(param);
		param = new BasicNameValuePair("gflags", "R");
		requestParameter.add(param);
		param = new BasicNameValuePair("appid",
				ApplicationConstants.API_KEY_YAHOO);
		requestParameter.add(param);
		httpServiceHelper.setRequestParameter(requestParameter);
	}

}
